import JsPDF from "jspdf";
import html2canvas from "html2canvas";

const A4_WIDTH = 592.28;
const A4_HEIGHT = 841.89;
// 将元素转化为canvas元素
// 通过 放大 提高清晰度
// width为内容宽度
async function toCanvas(element, width) {
  // canvas元素
  const canvas = await html2canvas(element, {
    // allowTaint: true, // 允许渲染跨域图片
    scale: window.devicePixelRatio * 2, // 增加清晰度
    useCORS: true, // 允许跨域
    onrendered: function(canvas) {
      document.body.appendChild(canvas);
    },
  });
  // 获取canavs转化后的宽度
  const canvasWidth = canvas.width;
  // 获取canvas转化后的高度
  const canvasHeight = canvas.height;
  // 高度转化为PDF的高度
  const height = (width / canvasWidth) * canvasHeight;
  // 转化成图片Data
  const canvasData = canvas.toDataURL("image/jpeg", 1.0);
  // console.log(canvasData)
  return {
    width,
    height,
    data: canvasData,
  };
}
/**
 * 生成pdf(A4多页pdf截断问题， 包括页眉、页脚 和 上下左右留空的护理)
 * @param {Object} param
 * @param {HTMLElement} param.element - 需要转换的dom根节点
 * @param {number} [param.contentWidth=550] - 一页pdf的内容宽度，0-592.28
 * @param {string} [param.filename='document.pdf'] - pdf文件名
 * @param {HTMLElement} param.header - 页眉dom元素
 * @param {HTMLElement} param.footer - 页脚dom元素
 */
export async function outputPDF({
  element,
  contentWidth = 550,
  footer,
  header,
}) {
  if (!(element instanceof HTMLElement)) {
    return;
  }
  // jsPDFs实例
  const pdf = new JsPDF({
    unit: "pt",
    format: "a4",
    orientation: "p",
  });

  // 一页的高度， 转换宽度为一页元素的宽度
  const { width, height, data } = await toCanvas(element, contentWidth);

  // 添加页头
  // async function addHeader(header, pdf, contentWidth) {
  //   const {
  //     height: headerHeight,
  //     data: headerData,
  //     width: hWidth,
  //   } = await toCanvas(header, contentWidth);
  //   // pdf.addImage(headerData, 'JPEG', 0, 0, contentWidth, headerHeight);
  // }

  // 添加页脚
  async function addFooter(pageNum, now, footer, pdf, contentWidth) {
    const newFooter = footer.cloneNode(true);
    newFooter.querySelector(".pdf-footer-page").innerText = now;
    newFooter.querySelector(".pdf-footer-page-count").innerText = pageNum;
    document.documentElement.append(newFooter);
    const {
      height: footerHeight,
      data: footerData,
      // width: fWidth,
    } = await toCanvas(newFooter, contentWidth);
    document.documentElement.removeChild(newFooter);
    pdf.addImage(
      footerData,
      "JPEG",
      0,
      A4_HEIGHT - footerHeight,
      contentWidth,
      footerHeight
    );
  }

  // 添加
  function addImage(_x, _y, pdf, data, width, height) {
    pdf.addImage(data, "JPEG", _x, _y, width, height);
  }

  // 增加空白遮挡
  function addBlank(x, y, width, height, pdf) {
    pdf.setFillColor(255, 255, 255);
    pdf.rect(x, y, Math.ceil(width), Math.ceil(height), "F");
  }

  // 页脚元素 经过转换后在PDF页面的高度
  const { height: tfooterHeight } = await toCanvas(footer, contentWidth);

  // 页眉元素 经过转换后在PDF的高度
  // const { height: theaderHeight } = await toCanvas(header, contentWidth);
  const theaderHeight = 0;
  // 距离PDF左边的距离，/ 2 表示居中
  const baseX = (A4_WIDTH - contentWidth) / 2; // 预留空间给左边
  // 距离PDF 页眉和页脚的间距， 留白留空
  const baseY = 15;

  // 出去页头、页眉、还有内容与两者之间的间距后 每页内容的实际高度
  const originalPageHeight =
    A4_HEIGHT - tfooterHeight - theaderHeight - 2 * baseY;

  // 元素在网页页面的宽度
  const elementWidth = element.offsetWidth;

  // PDF内容宽度 和 在HTML中宽度 的比， 用于将 元素在网页的高度 转化为 PDF内容内的高度， 将 元素距离网页顶部的高度  转化为 距离Canvas顶部的高度
  const rate = contentWidth / elementWidth;

  // 每一页的分页坐标， PDF高度， 初始值为根元素距离顶部的距离
  console.log(getElementTop(element));
  const tempH = rate * getElementTop(element);
  const tempHeaderH = rate * 88;
  console.log(tempH, tempHeaderH);
  const pages = [0];

  // 获取元素距离网页顶部的距离
  // 通过遍历offsetParant获取距离顶端元素的高度值
  function getElementTop(element) {
    let actualTop = element.offsetTop;
    let current = element.offsetParent;

    while (current && current !== null) {
      actualTop += current.offsetTop;
      current = current.offsetParent;
    }
    return actualTop;
  }

  // 顶部标题与底部签名
  // let headerEle = null;
  let footerEle = null;
  // 当前页面内容高度
  // let pageContentH = 0;
  // 遍历正常的元素节点
  function traversingNodes(nodes, isFirst, isPicture) {
    for (let i = 0; i < nodes.length; ++i) {
      const node = nodes[i];
      if (isFirst) {
        footerEle = nodes[2];
        i === 1 && traversingNodes(node.childNodes);
      } else {
        // 一个是标题下的信息  一个是未显示的side
        if (
          node.classList.contains("system-user-form_pdf") ||
          node.classList.contains("record-edit-form-container_aside")
        ) {
          continue;
        }
        if (node.classList.contains("target-card-item") || isPicture) {
          // 需要特殊处理图片，因为图片得target-card-item类名是一个集合，需要判断每一张图片是否需要分页

          const tempNode = node.getElementsByClassName(
            "el-upload-list--picture-card"
          )[0];

          if (tempNode && !isPicture) {
            traversingNodes(tempNode.childNodes, false, true);
            continue;
          }
          const offsetHeight = node.offsetHeight;
          // 计算出最终高度
          let offsetTop = getElementTop(node);

          // dom转换后距离顶部的高度
          // 转换成canvas高度
          if (offsetTop === undefined) {
            offsetTop = 0;
          }
          const top = rate * offsetTop - tempH;

          updatePos(rate * offsetHeight, top);
        } else {
          traversingNodes(node.childNodes);
        }
      }
    }
  }

  // 可能跨页元素位置更新的方法
  // 需要考虑分页元素，则需要考虑两种情况
  // 1. 普通达顶情况，如上
  // 2. 当前距离顶部高度加上元素自身高度 大于 整页高度，则需要载入一个分页点
  function updatePos(eheight, top) {
    const prevPageEnd = pages[pages.length - 1]; // 前一个元素所在页面的结束位置
    // 如果单个元素高度已经超过当前页，则证明可以分页了
    if (top - prevPageEnd >= originalPageHeight) {
      pages.push(prevPageEnd + originalPageHeight);
    } else if (
      top + eheight - prevPageEnd > originalPageHeight &&
      top !== prevPageEnd
    ) {
      // 若 距离当前页顶部的高度 加上元素自身的高度 大于 一页内容的高度, 则证明元素跨页，将当前高度作为分页位置
      pages.push(top);

      if (eheight > originalPageHeight) {
        // 处理超长元素的分页
        const numPages = Math.ceil(eheight / originalPageHeight);
        for (let i = 1; i < numPages; i++) {
          pages.push(pages[pages.length - 1] + originalPageHeight);
        }
      }
    }
  }

  // 深度遍历节点的方法
  traversingNodes(element.childNodes, true);

  const offsetHeight = footerEle.offsetHeight;
  // 计算出最终高度
  let footerOffsetTop = getElementTop(footerEle);

  // dom转换后距离顶部的高度
  // 转换成canvas高度
  if (footerOffsetTop === undefined) {
    footerOffsetTop = 0;
  }
  const footerTop = rate * footerOffsetTop - tempH;
  updatePos(rate * offsetHeight, footerTop);
  console.log({ pages, contentWidth, width, height });

  // 根据分页位置 开始分页
  for (let i = 0; i < pages.length; ++i) {
    // message.success(`共${pages.length}页， 生成第${i + 1}页`)
    // 根据分页位置新增图片
    addImage(baseX, baseY + theaderHeight - pages[i], pdf, data, width, height);
    // 将 内容 与 页眉之间留空留白的部分进行遮白处理
    addBlank(0, theaderHeight, A4_WIDTH, baseY, pdf);
    // 将 内容 与 页脚之间留空留白的部分进行遮白处理
    addBlank(0, A4_HEIGHT - baseY - tfooterHeight, A4_WIDTH, baseY, pdf);
    // 对于除最后一页外，对 内容 的多余部分进行遮白处理
    if (i < pages.length - 1) {
      // 获取当前页面需要的内容部分高度
      const imageHeight = pages[i + 1] - pages[i];
      // 对多余的内容部分进行遮白
      addBlank(
        0,
        baseY + imageHeight + theaderHeight,
        A4_WIDTH,
        A4_HEIGHT - imageHeight,
        pdf
      );
    }
    if (i !== 0) {
      // 添加页眉
    }
    // await addHeader(header, pdf, A4_WIDTH)

    // 添加页脚
    await addFooter(pages.length, i + 1, footer, pdf, A4_WIDTH);

    // 若不是最后一页，则分页
    if (i !== pages.length - 1) {
      // 增加分页
      pdf.addPage();
    }
  }
  // return pdf.save(filename)

  return pdf.output("datauristring");
}

// 下载pdf
// baseData是后端传来的base64,fileName是文件名
export function fileDownload(baseData, fileName, zip) {
  // const URL = dataURLtoBlob(baseData.substring(baseData.indexOf(',') + 1));
  return new Promise((resolve) => {
    if (zip) {
      resolve({
        PDF: baseData,
        name: fileName,
      });
      return;
    }
    var reader = new FileReader();
    reader.readAsDataURL(baseData);
    reader.onload = function(e) {
      // 兼容IE
      if (window.navigator.msSaveOrOpenBlob) {
        var bstr = atob(e.target.result.split(",")[1]);
        var n = bstr.length;
        var u8arr = new Uint8Array(n);
        while (n--) {
          u8arr[n] = bstr.charCodeAt(n);
        }
        var blob = new Blob([u8arr]);
        window.navigator.msSaveOrOpenBlob(blob, fileName);
      } else {
        // 转换完成，创建一个a标签用于下载
        const a = document.createElement("a");
        a.download = fileName; // 这里写你的文件名
        a.href = e.target.result;
        document.body.appendChild(a);
        a.click();
        document.body.removeChild(a);
      }
      resolve();
    };
  });
}
